home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- CDragAcrossTable.c
-
- This is an examples class that works with CDragAcrossTask to drag the
- selected cells to another postion within the current table or another
- CDragAcrossTable in the applicaiton.
-
- This is a subclass of CTable, but it can be made a subclass of any CTable
- subclass, such as CArrayPane. Too bad I can't/don't use
- multiple-inheritance.
-
- AUTHOR: Andrew_Gilmartin@Brown.Edu
- MODIFIED: 93-11-04
-
- Copyright (C) 1993 by Brown University. All rights reserved.
-
- Permission is granted to any individual or institution to use, copy,
- or redistribute the binary version of this software and its
- documentation provided this notice and the copyright notices are
- retained. Permission is granted to any individual or non-profit
- institution to use, copy, modify, or redistribute the source files
- of this software provided this notice and the copyright notices are
- retained. This software may not be distributed for profit, either
- in original form or in derivative works, nor can the source be
- distributed to other than an individual or a non-profit institution.
- Any individual or group interested in seeing and/or using these
- source files but who are prevented from doing so by the above
- constraints should contact Don Wolfe, Vice-President for Computer
- Systems at Brown University, (401) 863-7247, for possible
- software licensing of the source developed at Brown.
-
- Brown University and Andrew James Gilmartin make no representations
- about the suitability of this software for any purpose.
-
- BROWN UNIVERSITY AND ANDREW JAMES GILMARTIN GIVE NO WARRANTY, EITHER
- EXPRESS OR IMPLIED, FOR THE PROGRAM AND/OR DOCUMENTATION PROVIDED,
- INCLUDING, WITHOUT LIMITATION, WARRANTY OF MERCHANTABILITY AND
- WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE.
-
- ******************************************************************************/
-
- #include "ForgetRgn.h"
- #include "CDragAcrossTask.h"
- #include "CDragAcrossTable.h"
-
- #define IS_EVEN( _n ) \
- ( ( (_n) & 0x01 ) == 0 )
-
- enum { kBoundarySize = 4 }; // used by DragRowBoundary() & DrawColBoundary()
-
- enum { kAutoScrollSlop = 10 }; // used by ShouldScroll()
-
- Boundary kEmptyBoundary = { -1, -1 };
-
-
-
- /******************************************************************************
- IDragAcrossTable
-
- Initilaize the drag across table.
- ******************************************************************************/
-
- void CDragAcrossTable::IDragAcrossTable
- ( CView* anEnclosure
- , CBureaucrat* aSupervisor
- , short aWidth
- , short aHeight
- , short aHEncl
- , short aVEncl
- , SizingOption aHSizing
- , SizingOption aVSizing )
- {
- ITable
- ( anEnclosure
- , aSupervisor
- , aWidth
- , aHeight
- , aHEncl
- , aVEncl
- , aHSizing
- , aVSizing );
-
- itsSelectedBoundaries = kEmptyBoundary;
-
- } /* IDragAcrossTable */
-
-
-
- /******************************************************************************
- MoveSelection
-
- This method is called by CDragAcrossTask should the user select a boundary
- to move the selection to.
- ******************************************************************************/
-
- void CDragAcrossTable::MoveSelection( CDragAcrossTable* toTable, Boundary toBoundary )
- {
- /* nop */
-
- } /* MoveSelection */
-
-
-
- /******************************************************************************
- DoClick
-
- Did the user click to drag or click to select? Act approp.
- ******************************************************************************/
-
- void CDragAcrossTable::DoClick( Point hitPt, short modifierKeys, long when )
- {
- CDragAcrossTask* dragTask;
- Cell hitCell;
- LongPt pt;
- Point startPt;
-
- QDToFrame( hitPt, &pt );
-
- if ( PtInLongRect( &pt, &bounds ) )
- {
- if ( HitDragZone( hitPt, modifierKeys ) )
- {
-
- dragTask = MakeGlobalMouseTask();
-
- FrameToGlobal( &pt, &startPt );
- TrackGlobalMouse( dragTask, startPt );
-
- ForgetObject( dragTask );
- }
- else
- {
- inherited::DoClick( hitPt, modifierKeys, when );
- }
- }
- else
- {
- ClickOutsideBounds( hitPt, modifierKeys, when);
- }
-
- } /* DoClick */
-
-
-
- /******************************************************************************
- HitDragZone
-
- Called by DoClick() to determine if the user has clicked in the "drag
- zone."
- ******************************************************************************/
-
- Boolean CDragAcrossTable::HitDragZone( Point hitPt, short modifierKeys )
- {
- return ( modifierKeys & controlKey ) != 0;
-
- } /* HitDragZone */
-
-
-
- /******************************************************************************
- MakeGlobalMouseTask
-
- Create the global mouse task. NOTE: aNameIndex of 130 is the TCL default.
- ******************************************************************************/
-
- CDragAcrossTask* CDragAcrossTable::MakeGlobalMouseTask( void )
- {
- CDragAcrossTask* dragTask = NULL;
-
- TRY
- {
- dragTask = new CDragAcrossTask;
- dragTask->IDragAcrossTask( this, GetSelectionRgn(), 130 );
- }
- CATCH
- {
- ForgetObject( dragTask );
- }
- ENDTRY
-
- return dragTask;
-
- } /* MakeGlobalMouseTask */
-
-
-
- /******************************************************************************
- Draw
-
- Draw the content plus the selected boundaries. Assume the pane is
- already prepared.
- ******************************************************************************/
-
- void CDragAcrossTable::Draw( Rect *area )
- {
- inherited::Draw( area );
-
- /* Update the boundary selection */
-
- if ( ! EqualPt( itsSelectedBoundaries, kEmptyBoundary ) )
- {
- DrawColBoundary( itsSelectedBoundaries );
- DrawRowBoundary( itsSelectedBoundaries );
- }
-
- } /* Draw */
-
-
-
- /******************************************************************************
- DrawRowBoundary
-
- Hilight the row boundary. Assumes the pane is already prepared.
- ******************************************************************************/
-
- void CDragAcrossTable::DrawRowBoundary( Boundary boundaries )
- {
- LongRect pixels;
- Rect visPixels;
- short col;
- short row;
-
- /* Make sure there is a row boundary */
-
- if ( boundaries.v == kEmptyBoundary.v )
- return;
-
- /* Get boundary's horizontal position and length */
-
- col = boundaries.h / 2;
-
- pixels.left = GetColStart( col );
- pixels.right = pixels.left + GetColWidth( col );
-
- pixels.left += kBoundarySize / 2,
- pixels.right -= kBoundarySize / 2; // HACK: Makes it look a little better
-
- /* Get boundary's vertical position and height */
-
- row = boundaries.v / 2;
-
- if ( IS_EVEN( boundaries.v ) )
- {
- // Boundary at the top of the cell
-
- pixels.top = GetRowStart( row ) - kBoundarySize / 2;
- pixels.bottom = pixels.top + kBoundarySize;
- }
- else
- {
- // Boundary at the bottom of the cell
-
- pixels.bottom
- = GetRowStart( row )
- + GetRowHeight( row )
- + kBoundarySize / 2;
- pixels.top = pixels.bottom - kBoundarySize;
- }
-
- /* Draw boundary rect */
-
- if ( SectAperture( &pixels, &visPixels ) )
- {
- SetHiliteMode(); // Invert with user's hilite color
- InvertRect( &visPixels );
- }
-
- } /* DrawRowBoundary */
-
-
-
- /******************************************************************************
- DrawColBoundary
-
- Hilight the column boundary. Assumes the pane is already prepared.
- ******************************************************************************/
-
- void CDragAcrossTable::DrawColBoundary( Boundary boundaries )
- {
- LongRect pixels;
- Rect visPixels;
- short col;
- short row;
-
- /* Make sure there is a column boundary */
-
- if ( boundaries.h == kEmptyBoundary.h )
- return;
-
- /* Get boundary's vertical position and height */
-
- row = boundaries.v / 2;
-
- pixels.top = GetRowStart( row );
- pixels.bottom = pixels.top + GetRowHeight( row );
-
- pixels.top -= kBoundarySize / 2,
- pixels.bottom += kBoundarySize / 2; // HACK: Makes it look a little better
-
- /* Get boundary's horizontal position and length */
-
- col = boundaries.h / 2;
-
- if ( IS_EVEN( boundaries.h ) )
- {
- // Boundary to the left of the column
-
- pixels.left = GetColStart( col ) - kBoundarySize / 2;
- pixels.right = pixels.left + kBoundarySize;
- }
- else
- {
- // Boundary to the right of the column
-
- pixels.right
- = GetColStart( col )
- + GetColWidth( col )
- + kBoundarySize / 2;
- pixels.left = pixels.right - kBoundarySize;
- }
-
- /* Draw boundary rect */
-
- if ( SectAperture( &pixels, &visPixels ) )
- {
- SetHiliteMode(); // Invert with user's hilite color
- InvertRect( &visPixels );
- }
-
- } /* DrawColBoundary */
-
-
-
- /******************************************************************************
- SelectBoundaries
-
- Select the cell boundaries. Assumes the pane is already prepared.
- ******************************************************************************/
-
- void CDragAcrossTable::SelectBoundaries( Boundary boundaries )
- {
- if ( ! EqualPt( itsSelectedBoundaries, boundaries ) )
- {
- /*If necessary deselect/draw the previous boundaries */
-
- if ( ! EqualPt( itsSelectedBoundaries, kEmptyBoundary ) )
- {
- DrawColBoundary( itsSelectedBoundaries );
- DrawRowBoundary( itsSelectedBoundaries );
- }
-
- itsSelectedBoundaries = boundaries;
-
- /* select/draw new boundaries */
-
- DrawColBoundary( itsSelectedBoundaries );
- DrawRowBoundary( itsSelectedBoundaries );
- }
-
- } /* SelectBoundaries */
-
-
-
- /******************************************************************************
- FindBoundaries
-
- Find the boundaries what were hit.
- ******************************************************************************/
-
- void CDragAcrossTable::FindBoundaries( LongPt* hitPt, Boundary* hitBoundary )
- {
- hitBoundary->v = FindRowBoundary( hitPt->v );
- hitBoundary->h = FindColBoundary( hitPt->h );
-
- } /* FindBoundaries */
-
-
-
- /******************************************************************************
- FindRowBoundary
-
- Return the row boundary index for the given vertical offset. The
- boundary index indicates both the row and the side of the row. To
- determine the row divide the index by two. To determine which side
- test the index for even-ness; an even index means the boundary is at the
- top and an odd index means at the bottom.
- ******************************************************************************/
-
- short CDragAcrossTable::FindRowBoundary( long vLoc )
- {
- short row;
- long middle;
-
- if ( vLoc >= bounds.bottom )
- {
- row = ( tableBounds.bottom * 2 ) + 1;
- }
- else
- {
- /* Find the row the vLoc is in. */
-
- vLoc -= topLeftIndent.v;
- row = itsRows->FindSum( vLoc ) - 1;
- if ( row < 0 )
- row = 0;
-
- /* Is the boundary to the top or bottom. Which side of the middle? */
-
- middle = GetRowStart( row ) + GetRowHeight( row ) / 2;
-
- if ( vLoc < middle )
- row = row * 2; // top
- else
- row = row * 2 + 1; // bottom
- }
-
- return row;
-
- } /* FindRowBoundary */
-
-
-
- /******************************************************************************
- FindColBoundary
-
- Return the column boundary index for the given horizontal offset. The
- boundary index indicates both the column and the side of the column. To
- determine the column divide the index by two. To determine which side
- test the index for even-ness; an even index means the boundary is to the
- left and an odd index means to the left.
- ******************************************************************************/
-
- short CDragAcrossTable::FindColBoundary( long hLoc )
- {
- short col;
- long middle;
-
- if ( hLoc >= bounds.right )
- {
- col = ( tableBounds.right * 2 ) + 1;
- }
- else
- {
- /* Find the column the hLoc is in. */
-
- hLoc -= topLeftIndent.h;
- col = itsCols->FindSum( hLoc ) - 1;
- if ( col < 0 )
- col = 0;
-
- /* Is the boundary to the left or right. Which side of the middle? */
-
- middle = GetColStart( col ) + GetColWidth( col ) / 2;
-
- if ( hLoc < middle )
- col = col * 2; // left
- else
- col = col * 2 + 1; // right
- }
-
- return col;
-
- } /* FindColBoundary */
-
-
-
- /******************************************************************************
- GetSelectionRgn
-
- Return a region that represents the selection. This methed is used by
- CDragAcrossTask.
- ******************************************************************************/
-
- RgnHandle CDragAcrossTable::GetSelectionRgn( void )
- {
- RgnHandle cellRgn = NULL;
- RgnHandle selectionRgn = NULL;
- LongRect cellRect;
- Rect cellQDRect;
- Cell cell;
-
- TRY
- {
- cellRgn = NewRgn();
- selectionRgn = NewRgn();
-
- Prepare();
-
- /* Brute force iteration over the whole table. I can't seem to figure
- out how to get GetSelect() to work. */
-
- for ( cell.h = tableBounds.left; cell.h < tableBounds.right + 1; cell.h++ )
- {
- for ( cell.v = tableBounds.top; cell.v < tableBounds.bottom + 1; cell.v++ )
- {
- if ( IsSelected( cell ) )
- {
- /* Make cell region */
-
- GetCellRect( cell, &cellRect );
- InsetLongRect( &cellRect, 1, 1 );
- FrameToGlobalR( &cellRect, &cellQDRect );
- RectRgn( cellRgn, &cellQDRect );
-
- /* Add cell region to selection region */
-
- UnionRgn( cellRgn, selectionRgn, selectionRgn );
- }
- }
- }
-
- DisposeRgn( cellRgn );
- }
- CATCH
- {
- ForgetRgn( cellRgn );
- ForgetRgn( selectionRgn );
- }
- ENDTRY
-
- return selectionRgn;
-
- } /* GetSelectionRgn */
-
-
-
- /******************************************************************************
- AutoScroll
-
- Scroll the table if necessary. See ShouldScroll() for more information
- about scrolling with CDragAcrossTable.
- ******************************************************************************/
-
- Boolean CDragAcrossTable::AutoScroll( LongPt* mouseLoc )
- {
- Point theDelta;
-
- if ( ShouldScroll( mouseLoc, &theDelta ) )
- {
- Scroll( theDelta.h, theDelta.v, TRUE );
- if ( itsScrollPane != NULL )
- {
- itsScrollPane->Calibrate();
- }
- Prepare();
-
- return TRUE;
- }
- else
- {
- return FALSE;
- }
-
- } /* AutoScroll */
-
-
-
- /******************************************************************************
- ShouldScroll
-
- Determine whether the table should scroll given the current mouse location.
- Return true or false approp. plus the scrolling delta. (Code taken from
- CPanoram::AutoScroll().)
-
- To aid scrolling when the mouse is within the table, this override checks
- if the mouseLoc is near the edge of the frame. Near the edge is defined
- as kAutoScrollSlop. The reason for scrolling when the mouse is in the
- table is that when CDragAcrossTask has content the current table will lose
- focus when the mouse moves outside of the frame. Having the slop allows
- the user to autoscroll within the table.
- ******************************************************************************/
-
- Boolean CDragAcrossTable::ShouldScroll( LongPt* mouseLoc, Point* delta )
- {
- short hDelta = 0;
- short vDelta = 0;
- short hSpan;
- short vSpan;
- short hStep = 1;
- short vStep = 1;
-
- GetFrameSpan(&hSpan, &vSpan);
-
- GetSteps( &hStep, &vStep ); // TCL 1.1.3 11/30/92 BF
-
- if (mouseLoc->h < frame.left + kAutoScrollSlop ) {
- hDelta = Max(-hStep, bounds.left - position.h);
- if (hDelta > 0) {
- hDelta = 0;
- }
- } else if (mouseLoc->h > frame.right - kAutoScrollSlop ) {
- hDelta = Min(hStep, bounds.right - position.h - hSpan);
- if (hDelta < 0) {
- hDelta = 0;
- }
- }
-
- if (mouseLoc->v < frame.top + kAutoScrollSlop ) {
- vDelta = Max(-vStep, bounds.top - position.v);
- if (vDelta > 0) {
- vDelta = 0;
- }
- } else if (mouseLoc->v > frame.bottom - kAutoScrollSlop ) {
- vDelta = Min(vStep, bounds.bottom - position.v - vSpan);
- if (vDelta < 0) {
- vDelta = 0;
- }
- }
-
- if ( ( hDelta != 0 ) || ( vDelta != 0 ) )
- {
- if ( delta != NULL ) // Some callers might not care about the actual delta
- SetPt( delta, hDelta, vDelta );
- return(TRUE);
- }
- else
- {
- return(FALSE);
- }
-
- } /* ShouldScroll */
-
-
-
- /******************************************************************************
- TrackGlobalMouse
-
- Similar to TrackMouse() but all the coordinates are in the global (ie
- CDesktop) coordinate system. (Perhaps I should generalize this to be any
- view's coordinate system.
- ******************************************************************************/
-
- void CDragAcrossTable::TrackGlobalMouse( CGlobalMouseTask* aTask, Point startPt )
- {
- Point currPt;
- Point prevPt;
- EventRecord macEvent;
-
- currPt = prevPt = startPt;
-
- aTask->BeginTracking( startPt );
-
- while ( StillDown() )
- {
- gDesktop->Prepare();
- GetMouse( &currPt );
-
- aTask->KeepTracking( currPt, prevPt, startPt );
- prevPt = currPt;
- }
-
- gDesktop->Prepare();
- if ( OSEventAvail( mUpMask, &macEvent ) )
- {
- currPt = macEvent.where;
- }
-
- aTask->EndTracking( currPt, prevPt, startPt );
-
- } /* TrackGlobalMouse */
-
-
-
- /******************************************************************************
- FrameToGlobal
-
- Convert a LongPt from Frame to Global coordinates.
- ******************************************************************************/
-
- void CDragAcrossTable::FrameToGlobal( LongPt* framePt, Point* globalPt )
- {
- Point offset;
-
- LongToQDPt( framePt, globalPt);
-
- offset = topLeft((**((WindowPeek)macPort)->contRgn).rgnBBox);
-
- globalPt->v += offset.v - vOrigin;
- globalPt->h += offset.h - hOrigin;
-
- } /* FrameToGlobal */
-
-
-